﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Csla;
using Csla.Data;
using System.Data;
using System.Threading;
using Csla.Validation;
using System.Data.Common;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;

namespace Asah.SiteWorx.Commerce
{
    [Serializable()]
    public class OrderItem : BusinessBase<OrderItem>
    {

        #region Business Methods

        private int _id = 0;
        private string _itemNumber = "";
        private string _productTitle = "";
        private decimal _unitPrice = 0;
        private int _quantity = 0;
                
        [System.ComponentModel.DataObjectField(true, true)]
        public int ID
        {
            get
            {
                CanReadProperty("ID", true);
                return _id;
            }
        }

        public string ItemNumber
        {
            get
            {
                CanReadProperty("ItemNumber", true);
                return _itemNumber;
            }
            set
            {
                CanWriteProperty("ItemNumber", true);
                if (_itemNumber != value)
                {
                    _itemNumber = value;
                    PropertyHasChanged("ItemNumber");
                }
            }
        }

        public string ProductTitle
        {
            get
            {
                CanReadProperty("ProductTitle", true);
                return _productTitle;
            }
            set
            {
                CanWriteProperty("ProductTitle", true);
                if (_productTitle != value)
                {
                    _productTitle = value;
                    PropertyHasChanged("ProductTitle");
                }
            }
        }

        public decimal UnitPrice
        {
            get
            {
                CanReadProperty("UnitPrice", true);
                return _unitPrice;
            }
            set
            {
                CanWriteProperty("UnitPrice", true);
                if (_unitPrice != value)
                {
                    _unitPrice = value;
                    PropertyHasChanged("UnitPrice");
                }
            }
        }

        public int Quantity
        {
            get
            {
                CanReadProperty("Quantity", true);
                return _quantity;
            }
            set
            {
                CanWriteProperty("Quantity", true);
                if (_quantity != value)
                {
                    _quantity = value;
                    PropertyHasChanged("Quantity");
                }
            }
        }

        public decimal Total
        {
            get
            {
                return _unitPrice * _quantity;
            }
        }

        protected override object GetIdValue()
        {
            return _id;
        }

        #endregion

        #region Validation Rules

        protected override void AddBusinessRules()
        {
            // add BusinessRules here
            ValidationRules.AddInstanceRule(ItemNumberRequired, "ItemNumber");
            ValidationRules.AddInstanceRule(ProductTitleRequired, "ProductTitle");
            ValidationRules.AddInstanceRule(ValidQuantity, "Quantity");
        }

        private bool ItemNumberRequired(object target, Csla.Validation.RuleArgs e)
        {
            if (_itemNumber.Length > 0)
            {
                return true;
            }
            else
            {
                e.Description = "Item number is required.";
                return false;
            }
        }

        private bool ProductTitleRequired(object target, Csla.Validation.RuleArgs e)
        {
            if (_productTitle.Length > 0)
            {
                return true;
            }
            else
            {
                e.Description = "Product title is required.";
                return false;
            }
        }

        private bool ValidQuantity(object target, Csla.Validation.RuleArgs e)
        {
            if (_quantity > 0)
            {
                return true;
            }
            else
            {
                e.Description = "Invalid quantity.";
                return false;
            }
        }

        #endregion

        #region Authorization Rules

        protected override void AddAuthorizationRules()
        {
            // add AuthorizationRules here
        }

        public static bool CanAddOrderItem()
        {
            return true;
        }

        public static bool CanGetOrderItem()
        {
            return true;
        }

        public static bool CanDeleteOrderItem()
        {
            return false;
        }

        public static bool CanEditOrderItem()
        {
            return false;
        }

        #endregion

        #region Factory Methods

        internal static OrderItem NewOrderItem()
        {
            return new OrderItem();
        }

        internal static OrderItem GetOrderItem(SafeDataReader dr)
        {
            return new OrderItem(dr);
        }

        private OrderItem()
        {
            MarkAsChild();
            ValidationRules.CheckRules();
        }

        private OrderItem(SafeDataReader dr)
        {
            MarkAsChild();
            Fetch(dr);
        }

        #endregion

        #region Data Access

        private void Fetch(SafeDataReader dr)
        {
            _id = dr.GetInt32("OrderItemId");
            _itemNumber = dr.GetString("ItemNumber");
            _productTitle = dr.GetString("ProductTitle");
            _unitPrice = dr.GetDecimal("UnitPrice");
            _quantity = dr.GetInt32("Quantity");
            
            MarkOld();
            ValidationRules.CheckRules();
        }

        internal void Insert(Order order)
        {
            // if we're not dirty then don't update the database
            if (!this.IsDirty) return;

            Database db = DatabaseFactory.CreateDatabase("SiteWorxCommerce");
            DbCommand dbCommand = db.GetStoredProcCommand("aspnet_OrderItems_AddOrderItem");
            db.AddInParameter(dbCommand, "ApplicationId", DbType.Guid, Site.GetSite().ApplicationId);
            db.AddInParameter(dbCommand, "OrderId", DbType.Int32, order.ID);
            db.AddInParameter(dbCommand, "ItemNumber", DbType.String, _itemNumber);
            db.AddInParameter(dbCommand, "ProductTitle", DbType.String, _productTitle);
            db.AddInParameter(dbCommand, "UnitPrice", DbType.Currency, _unitPrice);
            db.AddInParameter(dbCommand, "Quantity", DbType.Int32, _quantity);
                        
            try
            {
                _id = int.Parse(db.ExecuteScalar(dbCommand).ToString());
                dbCommand.Dispose();
            }
            catch (Exception ex)
            {
                bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Layer Policy");
                if (rethrow)
                {
                    throw;
                }
            }

            MarkOld();
        }

        #endregion

    }
}
